/*
 * SpeedoGradient - Speedometer and gradient  meter application for Android 
 * Copyright 2013 Guilhem VALENTIN
 * 
 * This file is part of SpeedoGradient
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with SpeedoGradient. If not, see <http://www.gnu.org/licenses/>.
 */
package com.gvalentin.speedogradient.data;

import android.location.Location;
import android.util.Log;

/**
 * Data manager for the application.
 * @author guilhem
 */
public class SpeedoGradientData {
	
	private static final String TAG = SpeedoGradientData.class.getSimpleName();
	
	
	// Max speed
	private double maxSpeed = 0.0f;

	// Distance
	private Calculator<Double> calculatorDistance = new CalculatorDistance();
	
	// Speed
	private Calculator<Double> calculatorSpeed = new CalculatorSpeed();
	
	// Average speed
	private Calculator<Double> calculatorSpeedAvg = new CalculatorSpeedAverage(this);
	
	// Acceleration
	private Calculator<Double> calculatorAccel = new CalculatorAcceleration();

	// Incline calculation
	private Calculator<Double> calculatorIncline = new CalculatorInclineAdaptative();
	
	// Incline (gradient and degrees)
	private double inclinePer = 0; // gradient
	private double inclineDeg = 0; // degrees
	
	// Previous location
    Location previous = null;
    
    
    /**
     * Constructor
     */
    public SpeedoGradientData() {
    }
    
    
	/**
	 * Get the speed (in m/s)
	 * @return the speed
	 */
	public double getSpeed() {
		return calculatorSpeed.getData();
	}
	
	/**
	 * Get the max speed (in m/s)
	 * @return the max speed
	 */
	public double getSpeedMax() {
		return maxSpeed;
	}

	/**
	 * Get the average speed (in m/s)
	 * @return the average speed
	 */
	public double getSpeedAverage() {
		return calculatorSpeedAvg.getData();
	}
	
	/**
	 * Get the acceleration (in m/s^2)
	 * @return the acceleration
	 */
	public double getAcceleration() {
		return calculatorAccel.getData();
	}
	
	/**
	 * Get the incline in degrees
	 * @return the incline
	 */
	public double getInclineDeg() {
		return inclineDeg;
	}
	
	/**
	 * Get the incline (elevation divided by distance)
	 * @return the incline
	 */
	public double getInclinePer() {
		return inclinePer;
	}
	
	/**
	 * Get total distance (m)
	 */
	public double getTotalDistance() {
		return calculatorDistance.getData();
	}

	/**
	 * Update current location
	 * @param current
	 */
	public void updateLocation(Location current) {
		Log.d(TAG, "updateLocation("+current+")");
		if (current != null) {
			// Distance
			calculatorDistance.update(previous, current);
			
			// Filter speed
			calculatorSpeed.update(previous, current);
			
			// Update maximum speed
			if (calculatorSpeed.getData() > maxSpeed) {
				maxSpeed = calculatorSpeed.getData();
			}
			
			// Update speed average
			calculatorSpeedAvg.update(previous, current);
			
			// Update acceleration
			calculatorAccel.update(previous, current);
			
			// Calculate incline from GPS location
			calculatorIncline.update(previous, current);
			inclinePer = calculatorIncline.getData(); // gradient
			inclineDeg = Math.toDegrees(Math.atan(inclinePer)); // degrees
			
			// Save location
			this.previous = current;
		}
	}
}
